<?php

namespace App\Http\Controllers\Postalapi;

class BaseEncode{

    private static $last2byte = "3";

    private static $last4byte = "15";

    private static $last6byte = "63";

    private static $lead6byte = "252";

    private static $lead4byte = "240";

    private static $lead2byte = "192";

    private static $encodeTable = [
        'A', 'B', 'C', 'D',
        'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
        'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
        'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
        'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
        '4', '5', '6', '7', '8', '9', '+', '/'
    ];

    /**编码 */
    public static function encode($str){
        $strLength = count($str);
        $strBuffer =  '';
        // var_dump($strBuffer);exit;
        $num = 0;
        $currentByte = 0;

        for ($i=0; $i < $strLength ; $i++) { 
            $num = $num % 8;
            while ($num < 8) {
                switch ($num) {
                    case 0:
                        $currentByte = $str[$i] & self::$lead6byte;
                        $currentByte = self::uright($currentByte,2);
                        break;
                    case 2:
                        $currentByte = ($str[$i] & self::$last6byte);
                        break;
                    case 4:
                        $currentByte = ($str[$i] & self::$last4byte);
                        $currentByte = ($currentByte << 2);
                        if (($i + 1) < $strLength) {
                            $currentByte |= self::uright(($str[$i + 1] & self::$lead2byte),6);
                        }
                        break;
                    case 6:
                        $currentByte = ($str[$i] & self::$last2byte);
                        $currentByte = ($currentByte << 4);
                        if (($i + 1) < $strLength) {
                            $currentByte |= self::uright(($str[$i + 1] & self::$lead4byte),4);
                        }
                        break;
                }
                
                $strBuffer = $strBuffer . self::$encodeTable[$currentByte];
                $num += 6;
            }
        }

        if (strlen($strBuffer) % 4 != 0) {
            for ($i = 4 - strlen($strBuffer) % 4; $i > 0; $i--) {
                $strBuffer = $strBuffer . "=";
            }
        }
        return $strBuffer;
    }

    /**无符号右移 */
    // private static function uright($a, $n)
    // {
    //     $c = 2147483647>>($n-1);
    //     return $c&($a>>$n);
    // }

    static function uright($integer, $n)
    {
        // convert to 32 bits
        if (0xffffffff < $integer || -0xffffffff > $integer)
        {
            $integer = fmod($integer, 0xffffffff + 1);
        }

        // convert to unsigned integer
        if (0x7fffffff < $integer) {
            $integer -= 0xffffffff + 1.0;
        }
        else if (-0x80000000 > $integer)
        {
            $integer += 0xffffffff + 1.0;
        }

        // do right shift
        if (0 > $integer)
        {
            // remove sign bit before shift
            $integer &= 0x7fffffff;
            // right shift
            $integer >>= $n;
            // set shifted sign bit
            $integer |= 1 << (31 - $n);
        }
        else
        {
            // use normal right shift
            $integer >>= $n;
        }

        return $integer;
    }
}
    